home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / netprog.zip / NETPROG.TAR / lib / dgsendrecv.c < prev    next >
C/C++ Source or Header  |  1989-12-17  |  3KB  |  114 lines

  1. /*
  2.  * Send a datagram to a server, and read a response.
  3.  * Establish a timer and resend as necessary.
  4.  * This function is intended for those applications that send a datagram
  5.  * and expect a response.
  6.  * Returns actual size of received datagram, or -1 if error or no response.
  7.  */
  8.  
  9. #include    <sys/types.h>
  10. #include    <sys/socket.h>
  11. #include    <signal.h>
  12. extern int    errno;
  13.  
  14. #include    "rtt.h"        /* our header for RTT calculations */
  15.  
  16. static struct rtt_struct   rttinfo;    /* used by rtt_XXX() functions */
  17. static int           rttfirst = 1;
  18. static int           tout_flag;    /* used in this file only */
  19.  
  20. int
  21. dgsendrecv(fd, outbuff, outbytes, inbuff, inbytes, destaddr, destlen)
  22. int        fd;        /* datagram socket */
  23. char        *outbuff;    /* pointer to buffer to send */
  24. int        outbytes;    /* #bytes to send */
  25. char        *inbuff;    /* pointer to buffer to receive into */
  26. int        inbytes;    /* max #bytes to receive */
  27. struct sockaddr *destaddr;    /* destination address */
  28.                 /* can be 0, if datagram socket is connect'ed */
  29. int        destlen;    /* sizeof(destaddr) */
  30. {
  31.     int    n;
  32.     int    to_alarm();        /* our alarm() signal handler */
  33.  
  34.     if (rttfirst == 1) {
  35.         rtt_init(&rttinfo);    /* initialize first time we're called */
  36.         rttfirst = 0;
  37.     }
  38.  
  39.     rtt_newpack(&rttinfo);        /* initialize for new packet */
  40. rexmit:
  41.     /*
  42.      * Send the datagram.
  43.      */
  44.  
  45.     if (sendto(fd, outbuff, outbytes, 0, destaddr, destlen) != outbytes) {
  46.         err_ret("dgsendrecv: sendto error on socket");
  47.         return(-1);
  48.     }
  49.  
  50.     signal(SIGALRM, to_alarm);
  51.     tout_flag = 0;            /* for signal handler */
  52.     alarm(rtt_start(&rttinfo));    /* calc timeout value & start timer */
  53.  
  54.     n = recvfrom(fd, inbuff, inbytes, 0,
  55.             (struct sockaddr *) 0, (int *) 0);
  56.     if (n < 0) {
  57.         if (tout_flag) {
  58.             /*
  59.              * The recvfrom() above timed out.
  60.              * See if we've retransmitted enough, and
  61.              * if so quit, otherwise try again.
  62.              */
  63.  
  64.             if (rtt_timeout(&rttinfo) < 0) {
  65. #ifdef    DEBUG
  66.                 err_ret("dgsendrecv: no response from server");
  67. #endif
  68.                 rttfirst = 1;    /* reinit if called again */
  69.                 return(-1);
  70.                     /* errno will be EINTR */
  71.             }
  72.  
  73.             /*
  74.              * We have to send the datagram again.
  75.              */
  76.  
  77.             errno = 0;        /* clear the error flag */
  78. #ifdef    DEBUG
  79.             err_ret("dgsendrecv: timeout, retransmitting");
  80.             rtt_d_flag = 1;
  81.             rtt_debug(&rttinfo);
  82. #endif
  83.             goto rexmit;
  84.         } else {
  85.             err_ret("dgsendrecv: recvfrom error");
  86.             return(-1);
  87.         }
  88.     }
  89.  
  90.     alarm(0);        /* stop signal timer */
  91.     rtt_stop(&rttinfo);    /* stop RTT timer, calc & store new values */
  92.  
  93. #ifdef    DEBUG
  94.     rtt_debug(&rttinfo);
  95. #endif
  96.  
  97.     return(n);        /* return size of received datagram */
  98. }
  99.  
  100. /*
  101.  * Signal handler for timeouts (SIGALRM).
  102.  * This function is called when the alarm() value that was set counts
  103.  * down to zero.  This indicates that we haven't received a response
  104.  * from the server to the last datagram we sent.
  105.  * All we do is set a flag and return from the signal handler.
  106.  * The occurrence of the signal interrupts the recvfrom() system call
  107.  * (errno = EINTR) above, and we then check the tout_flag flag.
  108.  */
  109.  
  110. to_alarm()
  111. {
  112.     tout_flag = 1;        /* set flag for function above */
  113. }
  114.